#include "reference.h"
using namespace sleek::core::serialise;

namespace sleek
{
    namespace core
    {
        namespace engine
        {
            reference::reference(core::u32 i) : id(i), TypeName(getSerialiseName())
            {
                addAttribute("ID", getId());
            }
            reference::~reference()
            {
            }
            /** ******************************** **/
            void reference::operator += (reference *_new)
            {
                addBloc(_new);
            }
            void reference::egals(reference *other)
            {
                clear();
                for(u32 i = 0; i<other->getNumberAttribute(); ++i)
                    addAttribute(other->info[i].name, other->info[i].value);
                for(u32 i = 0; i<other->getNumberBloc(); ++i)
                    addBloc(other->getBloc(i));
            }
            void reference::clear()
            {
                clearAttribute();
                clearBloc();
            }
            void reference::clearAttribute()
            {
                info.clear();
            }
            void reference::clearBloc()
            {
                bloc.clear();
            }
            /** ******************************** **/
            void reference::addBloc(reference *_new)
            {
                bloc.push_back(_new);
            }
            reference* reference::getBloc(u32 index)
            {
                return getNumberBloc() < index ? bloc[index] : 0;
            }
            reference* reference::getBloc(os::stringc name)
            {
                for(u32 i = 0; i<getNumberBloc(); ++i)
                    if(getBloc(i) && getBloc(i)->getSerialiseName() == name) return bloc[i];
                return 0;
            }
            void reference::removeBloc(os::stringc name)
            {
                for(u32 i = 0; i<getNumberBloc(); ++i)
                    if(getBloc(i) && getBloc(i)->getSerialiseName() == name) removeBloc(i);
            }
            void reference::removeBloc(u32 index)
            {
                bloc.erase(index);
            }
            u32 reference::getNumberBloc()
            {
                return bloc.size();
            }
            /** ******************************** **/
            void reference::addAttribute(os::stringc name, os::stringc value)
            {
                attribute tmp(name, value);
                info.push_back(tmp);
            }
            os::stringc reference::getAttribute(os::stringc name)
            {
                for(u32 i = 0; i<getNumberAttribute(); ++i)
                    if(info[i].name == name) return info[i].value;
                return "";
            }
            os::stringc reference::getAttribute(u32 index)
            {
                return getNumberAttribute() < index ? info[index].value : "";
            }
            void reference::removeAttribute(os::stringc name)
            {
                for(u32 i = 0; i<getNumberAttribute(); ++i)
                    if(info[i].name == name) removeAttribute(i);
            }
            void reference::removeAttribute(u32 index)
            {
                info.erase(index);
            }
            u32 reference::getNumberAttribute()
            {
                return info.size();
            }
            /** ******************************** **/
            os::stringc reference::serialise(const char *tablature)
            {
                os::stringc a, b(tablature);          b += "\t";
                    a += SerialiseBlocBegin(getSerialiseName(),tablature);
                    a += SerialiseLigne("NumberAttribute",info.size(),b.c_str());
                    a += SerialiseLigne("NumberBloc",bloc.size(),b.c_str());
                    for(unsigned short It = 0; It < info.size(); ++It) a += SerialiseLigne(info[It].name, info[It].value,b.c_str());
                    for(unsigned short It = 0; It < bloc.size(); ++It) if(bloc[It])  a += bloc[It]->serialise(b.c_str());
                    a += SerialiseBlocEnd(getSerialiseName(),tablature);
                return a;
            }
            void reference::unserialise(os::stringc src)
            {
                if(src.size() == 0) return;
                long next_pos = src.find("NumberBloc")+10;
                for(int i = 0; i < CharToInt(getSerialiseLigne(src,"NumberAttribute")); ++i)
                {
                    attribute *Ent = new attribute("Undefined","Nothink");
                        long loc1 = src.find("<",next_pos)+1, loc2 = src.find(" value = \"",loc1);
                        Ent->name = src.subStr(loc1,loc2-loc1);
                        Ent->value = getSerialiseLigne(src,Ent->name);
                        addAttribute(Ent->name,Ent->value);
                        next_pos = loc2;
                    delete Ent;
                }
                for(int i = 0; i < CharToInt(getSerialiseLigne(src,"NumberBloc")); ++i)
                {
                    reference *tmp = new reference();
                        tmp->TypeName = findNextBlocName(src,next_pos);
                        tmp->unserialise(getSerialiseBloc(src,tmp->TypeName,next_pos));
                    bloc.push_back(tmp);
                }
            }
        }
    }
}
